package com.ybl.store.backend.service.impl.store;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybl.store.backend.dao.entity.store.ProductDO;
import com.ybl.store.backend.dao.mapper.store.ProductMapper;
import com.ybl.store.backend.dto.UserInfoDTO;
import com.ybl.store.backend.dto.req.store.ProductSaveReqDTO;
import com.ybl.store.backend.dto.req.store.ProductUpdateReqDTO;
import com.ybl.store.backend.dto.resp.store.ProductNameRespDTO;
import com.ybl.store.backend.service.store.ProductService;
import com.ybl.store.common.constant.BanFlag;
import com.ybl.store.common.constant.DelFlag;
import com.ybl.store.common.constant.UserPermission;
import com.ybl.store.common.context.UserContext;
import com.ybl.store.common.convention.errorcode.BaseErrorCode;
import com.ybl.store.common.convention.exception.ClientException;
import com.ybl.store.common.entity.ListRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * 商品服务层
 */
@Service
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> implements ProductService {

    @Override
    public void saveProduct(ProductSaveReqDTO requestParam) {
        ProductDO productDO = BeanUtil.toBean(requestParam, ProductDO.class);
        productDO.setNumber(0);
        int result = baseMapper.insert(productDO);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_SAVE_ERROR);
        }
    }

    @Override
    public void deleteProduct(Long id) {
        int result = baseMapper.deleteById(id);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_DELETE_ERROR);
        }
    }

    @Override
    public void updateProduct(ProductUpdateReqDTO requestParam) {
        int result = baseMapper.updateById(BeanUtil.toBean(requestParam, ProductDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_UPDATE_ERROR);
        }
    }

    @Override
    public void banProduct(Long id, Integer banFlag) {
        ProductDO productDO = new ProductDO();
        productDO.setId(id);
        productDO.setBanFlag(banFlag);
        int result = baseMapper.updateById(productDO);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_BAN_ERROR);
        }
    }

    @Override
    public ListRespDTO<ProductDO> pageProduct(Integer pn, Integer ps, String name) {
        Long storeId = null;
        UserInfoDTO userInfoDTO = UserContext.get();
        if (!Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            storeId = userInfoDTO.getStoreId();
        }

        Page<ProductDO> page = new Page<>(pn, ps);
        LambdaQueryWrapper<ProductDO> lambdaQueryWrapper = Wrappers.lambdaQuery(ProductDO.class)
                .eq(Objects.nonNull(storeId), ProductDO::getStoreId, storeId)
                .like(Objects.nonNull(name), ProductDO::getName, name)
                .eq(ProductDO::getDelFlag, DelFlag.present)
                .orderByAsc(ProductDO::getName);
        Page<ProductDO> productPage = baseMapper.selectPage(page, lambdaQueryWrapper);

        return ListRespDTO.<ProductDO>builder()
                .total(productPage.getTotal())
                .items(productPage.getRecords())
                .build();
    }

    @Override
    public ListRespDTO<ProductNameRespDTO> listProductName() {
        Long storeId = null;
        UserInfoDTO userInfoDTO = UserContext.get();
        if (!Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            storeId = userInfoDTO.getStoreId();
        }

        LambdaQueryWrapper<ProductDO> lambdaQueryWrapper = Wrappers.lambdaQuery(ProductDO.class)
                .eq(Objects.nonNull(storeId), ProductDO::getStoreId, storeId)
                .eq(ProductDO::getDelFlag, DelFlag.present)
                .eq(ProductDO::getBanFlag, BanFlag.use)
                .orderByAsc(ProductDO::getName);
        List<ProductDO> productList = baseMapper.selectList(lambdaQueryWrapper);

        return ListRespDTO.<ProductNameRespDTO>builder()
                .total((long) productList.size())
                .items(productList
                        .stream()
                        .map(each -> BeanUtil.toBean(each, ProductNameRespDTO.class))
                        .toList())
                .build();
    }

    public void addNumber(Long productId, Integer number) {
        LambdaUpdateWrapper<ProductDO> lambdaQueryWrapper = Wrappers.lambdaUpdate(ProductDO.class)
                .eq(ProductDO::getId, productId)
                .setSql("number = number + " + number)
                .eq(ProductDO::getDelFlag, DelFlag.present)
                .eq(ProductDO::getBanFlag, BanFlag.use)
                .orderByAsc(ProductDO::getName);
        int result = baseMapper.update(lambdaQueryWrapper);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_UPDATE_ERROR);
        }
    }

    public void subNumber(Long productId, Integer number) {
        LambdaUpdateWrapper<ProductDO> lambdaQueryWrapper = Wrappers.lambdaUpdate(ProductDO.class)
                .eq(ProductDO::getId, productId)
                .setSql("number = number - " + number)
                .eq(ProductDO::getDelFlag, DelFlag.present)
                .eq(ProductDO::getBanFlag, BanFlag.use);
        int result = baseMapper.update(lambdaQueryWrapper);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.PRODUCT_UPDATE_ERROR);
        }
    }
}
